/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.core.tabbedproperties;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.views.properties.tabbed.AbstractPropertySection;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.NamedElement;

import com.cea.papyrus.core.editor.ModelManager;
import com.cea.papyrus.core.editpart.GraphEdgeEditPart;
import com.cea.papyrus.core.editpart.GraphNodeEditPart;
import com.cea.papyrus.core.editpart.IUMLElementEditPart;
import com.cea.papyrus.core.listener.PropertyViewListener;
import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.diagraminterchange2.di2.DiagramElement;

/**
 * Basic Papyrus implementation for property view section. Each section in papyrus should
 * override this section, not {@link AbstractPropertySection}.
 */
public class PropertyViewSection extends AbstractPropertySection {

	/**
	 * debug channel.
	 */
	protected final int channel = 23;

	/**
	 * the selected uml element
	 */
	protected Element umlElement = null;

	/**
	 * the listener to update the property view
	 */
	protected PropertyViewListener _umlListener = null;

	/**
	 * the diagram element that is selected in the diagram
	 */
	protected DiagramElement diagramElement = null;

	/**
	 * the edit part of the selected element
	 */
	protected IUMLElementEditPart<?> graphicalElement = null;

	/** UML label provider from editor */
	protected AdapterFactoryLabelProvider labelProvider = null;

	/** ModelManager from the selected edit part(s) * */
	protected ModelManager modelManager = null;

	/**
	 * {@inheritDoc}
	 */
	public void setInput(IWorkbenchPart part, ISelection selection) {
		super.setInput(part, selection);
		Object input = ((IStructuredSelection) selection).getFirstElement();
		// look for modelManager
		if (input instanceof IUMLElementEditPart<?>) {
			modelManager = ((IUMLElementEditPart<?>) input).getModelManager();
			labelProvider = modelManager.getLabelProvider();
		} else {
			Debug.log(IStatus.WARNING, "impossible to find the model manager from : " + input);
		}
		selectionChanged(selection);
	}

	/**
	 * Tells the section that the selection has changed.
	 */
	public void selectionChanged(ISelection selection) {
		Assert.isTrue(selection instanceof IStructuredSelection);
		// remove listeners on old selected element ()
		if (_umlListener != null && umlElement != null) {
			(umlElement).eAdapters().remove(_umlListener);
			_umlListener = null;
		}

		// add listener on the new element
		Object input = ((IStructuredSelection) selection).getFirstElement();

		if (input instanceof IUMLElementEditPart) {
			graphicalElement = (IUMLElementEditPart<?>) input;
			umlElement = ((IUMLElementEditPart<?>) input).getUmlElement();
			_umlListener = new PropertyViewListener(this);
			(umlElement).eAdapters().add(_umlListener);
			if ((input instanceof GraphNodeEditPart) || (input instanceof GraphEdgeEditPart)) {
				diagramElement = (DiagramElement) ((AbstractGraphicalEditPart) input).getModel();
			}
		}

	}

	/**
	 * 
	 * @return the uml element
	 */
	public Element getElement() {
		return umlElement;
	}

	/**
	 * {@inheritDoc}
	 */
	public void aboutToBeHidden() {
		// remove the listener on the uml element
		if (_umlListener != null && umlElement != null) {
			(umlElement).eAdapters().remove(_umlListener);
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public void dispose() {
		// remove the listener on the uml element
		if (_umlListener != null && umlElement != null) {
			umlElement.eAdapters().remove(_umlListener);
			_umlListener = null;
		}
		diagramElement = null;
		umlElement = null;
		graphicalElement = null;
	}

	/**
	 * Get the element editpart.
	 * 
	 * @return the element.
	 */
	public IUMLElementEditPart<?> getGraphicalElement() {
		return graphicalElement;
	}

	/**
	 * force refresh for named elements!!.
	 */
	public void forceToSave() {
		// FIXME remove this code section to force refresh
		if (getElement() instanceof NamedElement) {
			((NamedElement) getElement()).setName(((NamedElement) getElement()).getName());
		}
	}
	
	/**
	 * Returns <code>true</code> if the composite is not disposed and 
	 */
	public boolean isValid(Composite composite) {
		return (composite !=null && !composite.isDisposed());
	}

	/**
	 * Returns the model manager, which is given by the current selected edit part
	 * 
	 * @return the modelManager associated to the current selected edit part, or
	 *         <code>null</code> if no model manager was found from the selected edit
	 *         parts
	 */
	public ModelManager getModelManager() {
		return modelManager;
	}
	
	public AdapterFactoryLabelProvider getLabelProvider() {
		return labelProvider;
	}
}
